home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / nexttsrc.lha / nexttsources / sources / sys / eval.t < prev    next >
Text File  |  1988-02-05  |  34KB  |  894 lines

  1. (herald (tsys eval)    ;** dont change this herald
  2.         (env tsys (osys kernel)))
  3.  
  4. ;;; Copyright (c) 1985 Yale University
  5. ;;;     Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees.
  6. ;;; This material was developed by the T Project at the Yale University Computer 
  7. ;;; Science Department.  Permission to copy this software, to redistribute it, 
  8. ;;; and to use it for any purpose is granted, subject to the following restric-
  9. ;;; tions and understandings.
  10. ;;; 1. Any copy made of this software must include this copyright notice in full.
  11. ;;; 2. Users of this software agree to make their best efforts (a) to return
  12. ;;;    to the T Project at Yale any improvements or extensions that they make,
  13. ;;;    so that these may be included in future releases; and (b) to inform
  14. ;;;    the T Project of noteworthy uses of this software.
  15. ;;; 3. All materials developed as a consequence of the use of this software
  16. ;;;    shall duly acknowledge such use, in accordance with the usual standards
  17. ;;;    of acknowledging credit in academic research.
  18. ;;; 4. Yale has made no warrantee or representation that the operation of
  19. ;;;    this software will be error-free, and Yale is under no obligation to
  20. ;;;    provide any services, by way of maintenance, update, or otherwise.
  21. ;;; 5. In conjunction with products arising from the use of this material,
  22. ;;;    there shall be no use of the name of the Yale University nor of any
  23. ;;;    adaptation thereof in any advertising, promotional, or sales literature
  24. ;;;    without prior written consent from Yale in each case.
  25. ;;;
  26.  
  27. ;;;; The Evaluator
  28.  
  29. ;;; COMPILE is an S-expression preprocessor.  It takes source code,
  30. ;;; represented as S-expression, and makes a code tree.  Its main
  31. ;;; purposes are (a) expanding macros and (b) dead-reckoning local
  32. ;;; variable references.  This preprocessing makes code run faster
  33. ;;; than it would if a straightforward S-expression interpreter was
  34. ;;; used.
  35.  
  36. ;;; For the purposes of this module, the terms "static" and "global"
  37. ;;; both mean "free with respect to the expression being compiled".
  38. ;;; "Local" or "lambda-bound" mean "bound by some lambda-expression
  39. ;;; within the expression being compiled".
  40.  
  41. ;;; Code ("S-code") trees are represented as closures.  To interpret
  42. ;;; a code tree it is only necessary to call it.
  43.  
  44. ;;; A SHAPE is a compile-time structure which describes the
  45. ;;; representation that the local variable environment will have
  46. ;;; at runtime.
  47.  
  48. ;;; EVAL: copied from the T manual.
  49.  
  50. (define (eval exp env)
  51.   (run-compiled-code (standard-compiler exp (env-syntax-table env))
  52.                      env))
  53.  
  54. (define (standard-compiler exp syntax)
  55.   (compile-top exp syntax nil))
  56.  
  57. (lset *current-module* nil)
  58.  
  59. ;;; Like STANDARD-COMPILER, but gets its input from a port.  Sets
  60. ;;; up a compiled expression which is a loaded-file; i.e. handles
  61. ;;; LOADED-FILE-HERALD and LOADED-FILE-SOURCE appropriately.
  62.  
  63. (define-constant initial-exp-values (list (undefined-value "empty file")))
  64.  
  65.  
  66. (define (standard-compile-port port syntax herald)
  67.   (let ((source (port-name port)))
  68.     (bind ((*current-module* source))
  69.       (object nil
  70.               ((run-compiled-code self env)
  71.                (iterate loop ((vals initial-exp-values))
  72.                  (let ((exp (read port)))
  73.                    (cond ((eof? exp)
  74.                           (set port nil)            ;drop pointer
  75.                           (apply return vals))
  76.                          (else
  77.                           (receive vals
  78.                                    (run-compiled-code
  79.                                     (compile-top exp syntax self)
  80.                                     env)
  81.                             (load-print vals)
  82.                             (loop vals)))))))
  83.               ((compiled-code? self) '#t)
  84.               ((get-loaded-file self) self)
  85.               ((loaded-file-herald self) herald)
  86.               ((loaded-file-source self) source)
  87.               ((identification self)        ; For BACKTRACE
  88.                (filename-name (herald-filename herald)))
  89.               ((print-info self)
  90.                (filename-name (herald-filename herald)))
  91.               ((print-type-string self) "Loaded-file")))))
  92.  
  93. ;;; COMPILE-TOP - this is the top-level entry into the compiler.
  94. ;;; Keeps track of all variables free in the expression; when the
  95. ;;; code is actually run, it creates a vector where locatives to
  96. ;;; the variables can be stored.
  97.  
  98. (lset *syntax-table*   nil)
  99. (lset *free-vars*      nil)
  100. (lset *free-var-count* 0)
  101.  
  102. (define (compile-top exp syntax loaded-file)
  103.   (bind ((*free-vars* (make-table '*free-vars*))
  104.          (*free-var-count* 1)
  105.          (*syntax-table* syntax))
  106.     (let* ((code (compile exp loaded-file nil))
  107.            (free-var-count *free-var-count*))
  108.       (object nil
  109.               ((run-compiled-code self env)
  110.                (let ((env (enforce environment? env))
  111.                      (genv (vector-fill (make-vector free-var-count) nil)))
  112.                  (set (vref genv 0) env)
  113.                  ;? (add-active-segment env genv)
  114.                  (run code env genv)))
  115.               ((print-type-string self) "Compiled-code")))))
  116.  
  117. (define-integrable (genv-env genv) (vref genv 0))
  118.  
  119. ;;; ---- Local variable spec stuff.
  120.  
  121. ;;; Local variable specifiers (LVSPEC's) are implemented as fixnums
  122. ;;; divided into two bit fields, BACK and OVER.
  123.  
  124. (define-integrable lvspec? fixnum?)
  125.  
  126. (define-integrable (add-contour args lenv) (cons lenv args))
  127.  
  128. (define-integrable (lvspec back over)
  129.   (fixnum-logior back (fixnum-ashl over 13)))
  130.  
  131. (define-integrable (lvspec-back spec)
  132.   (fixnum-logand spec 8191))
  133.  
  134. (define-integrable (lvspec-over spec)
  135.   (fixnum-ashr spec 13))               ; signed
  136.  
  137. (define-integrable cenv-first cdr)
  138. (define-integrable cenv-rest  car)
  139. (define-integrable cenv-end?  atom?)
  140.  
  141. (define-integrable lenv-first cdr)
  142. (define-integrable lenv-rest  car)
  143. (define-integrable lenv-end?  atom?)
  144.  
  145. ;;; ---- Utilities for the stack debugger.
  146.  
  147. (define (interpreter-frame? frame)
  148.   ;; Incredible kludge.
  149.   (let ((z (get-loaded-file frame)))
  150.     (and z
  151.          (let ((fn (herald-filename (loaded-file-herald z))))
  152.            (and (eq? (filename-name fn) 'eval)
  153.                 (eq? (filename-dir fn) 'tsys)
  154.                 (frame-any scode? frame))))))
  155.  
  156. (define (interpreter-frame-code frame)
  157.   (frame-any (lambda (obj) (if (scode? obj) obj nil))
  158.              frame))
  159.  
  160. ;;; Called from GET-ENVIRONMENT.
  161.  
  162. (define (interpreter-frame-env frame)
  163.   (let ((code (interpreter-frame-code frame)))
  164.     (and code
  165.          (let ((shape (get-shape code)))
  166.            (and shape
  167.                 (let ((lenv (frame-any heuristically-lenv? frame)))
  168.                   (cond (lenv (make-local-env shape lenv))
  169.                         (else (get-environment shape)))))))))
  170.  
  171.  
  172. ;;; (RUN code lenv genv) -> value
  173. ;;;     is the way to run a piece of intermediate code.
  174.  
  175. (define-integrable (run code lenv genv)
  176.   (*run* lenv genv code))      ; make TN's pack better?? ;++ flush
  177.  
  178. (define (standard-run lenv genv code)
  179.   (cond ((lvspec? code)                 ; Local variable
  180.          (fetch-from-lenv code lenv))
  181.         ((extend? code)                 ; General expression
  182.          (code lenv genv))
  183.         (else                           ; Literal
  184.          code)))
  185.  
  186. (lset *run* standard-run)
  187.  
  188. ;;; (SCODE (LAMBDA (lenv genv) . body) . methods) is the standard
  189. ;;; way to create code tree nodes.  S-code is the term from MIT
  190. ;;; Scheme for intermediate code.
  191.  
  192. (lset *scode-count* 0)
  193.  
  194. ;++ changed for T3 objects
  195.  
  196. (define-local-syntax (scode . rest)
  197.   `(block (set *scode-count* (fx+ *scode-count* 1))
  198.           (object ,@rest 
  199.             ((scode? self) t)
  200.             ((disclose self)
  201.              (cond ((get-shape self)
  202.                     => (lambda (shape) (disclose-scode self shape)))
  203.                    (else nil)))
  204.             ((get-proc-name self)
  205.              (cond ((get-shape self)
  206.                     => get-proc-name)
  207.                    (else nil)))            ; ???
  208.             ((get-loaded-file self)
  209.              (cond ((get-shape self)
  210.                     => get-loaded-file)
  211.                    (else nil)))
  212.             ((print-type-string self) "Compiled-expression"))))
  213.  
  214. (define-predicate scode?)
  215.  
  216. (define-operation (get-shape code) nil)
  217.  
  218. (define (empty-shape) nil)
  219.  
  220. (define-operation (disclose-scode code shape)
  221.   (cond ((lvspec? code)
  222.          (invert-lvspec shape code))
  223.         ((extend? code)
  224.          '<expression>)
  225.         (else
  226.          `',code)))
  227.  
  228. (define (disclose-scode-list shape . stuff)
  229.   (map (lambda (code) (disclose-scode code shape)) stuff))
  230.  
  231. ;;; -------------------- Main dispatch.
  232.  
  233. (define (compile exp shape fn?)
  234.   (cond ((atom? exp)
  235.          (compile ((atom-expander *syntax-table*) exp) shape fn?))
  236.         ((not (proper-list? exp))
  237.          (compile-error shape "expression is an improper list~%  ~S" exp))
  238.         (else
  239.          (let ((head (car exp)))
  240.            (cond ((symbol? head)
  241.                   (cond ((syntax-table-entry *syntax-table* head)
  242.                          => (lambda (descr)
  243.                               (cond ((lambda-bound? shape head)
  244.                                      (warning
  245.  '("form beginning with symbol ~S is being interpreted as a~%"
  246.    "**~13tspecial form and not as a call~%"     ;Weird indentation^2
  247.    "**~13t~S~%")
  248.                                              head
  249.                                              exp)))
  250.                               (compile-special-form descr exp shape fn?)))
  251.                         (else
  252.                          (compile-call exp shape))))
  253.                  ((syntax-descriptor? head)
  254.                   (compile-special-form head exp shape fn?))
  255.                  (else
  256.                   (compile-call exp shape)))))))
  257.  
  258. (define (compile-special-form descr exp shape fn?)
  259.   (let ((new-exp (check-special-form-syntax descr exp)))
  260.     (cond ((neq? exp new-exp)
  261.            ;; An error was reported, and luser gave us a new form.
  262.            (compile new-exp shape fn?))
  263.           ((table-entry compilator-table descr)
  264.            ;; Syntax primitively understood by this evaluator.
  265.            => (lambda (proc) (proc descr exp shape fn?)))
  266.           (else
  267.            ;; Non-primitive syntax; assume it's a macro.
  268.            (compile (expand-macro-form descr exp *syntax-table*)
  269.                     shape
  270.                     fn?)))))
  271.  
  272. (define (compile-call exp shape)
  273.   (let ((proc (compile (car exp) shape t))
  274.         (args (map (lambda (arg) (compile arg shape nil))
  275.                    (cdr exp))))
  276.     (case (length (cdr exp))
  277.       ((0) (scode (lambda (lenv genv) ((run proc lenv genv)))
  278.                   ((get-shape self) shape)
  279.                   ((disclose-scode self shape)
  280.                    (disclose-scode-list shape proc))))
  281.       ((1) (let ((arg0 (car args)))
  282.              (scode (lambda (lenv genv)
  283.                       ((run proc lenv genv) (run arg0 lenv genv)))
  284.                     ((get-shape self) shape)
  285.                     ((disclose-scode self shape)
  286.                      (disclose-scode-list shape proc arg0)))))
  287.       ((2) (let ((arg0 (car args))
  288.                  (arg1 (cadr args)))
  289.              (scode (lambda (lenv genv)
  290.                       ((run proc lenv genv) (run arg0 lenv genv)
  291.                                             (run arg1 lenv genv)))
  292.                     ((get-shape self) shape)
  293.                     ((disclose-scode self shape)
  294.                      (disclose-scode-list shape proc arg0 arg1)))))
  295.       ((3) (let ((arg0 (car args))
  296.                  (arg1 (cadr args))
  297.                  (arg2 (caddr args)))
  298.              (scode (lambda (lenv genv)
  299.                       ((run proc lenv genv) (run arg0 lenv genv)
  300.                                             (run arg1 lenv genv)
  301.                                             (run arg2 lenv genv)))
  302.                     ((get-shape self) shape)
  303.                     ((disclose-scode self shape)
  304.                      (disclose-scode-list shape proc
  305.                                           arg0 arg1 arg2)))))
  306.       ((4) (let ((arg0 (car args))
  307.                  (arg1 (cadr args))
  308.                  (arg2 (caddr args))
  309.                  (arg3 (car (cdddr args))))
  310.              (scode (lambda (lenv genv)
  311.                       ((run proc lenv genv) (run arg0 lenv genv)
  312.                                             (run arg1 lenv genv)
  313.                                             (run arg2 lenv genv)
  314.                                             (run arg3 lenv genv)))
  315.                     ((get-shape self) shape)
  316.                     ((disclose-scode self shape)
  317.                      (disclose-scode-list shape proc
  318.                                           arg0 arg1 arg2 arg3)))))
  319.       (else (scode (lambda (lenv genv)
  320.                      (apply (run proc lenv genv)
  321.                             (map (lambda (arg) (run arg lenv genv))
  322.                                  args)))
  323.                    ((get-shape self) shape)
  324.                    ((disclose-scode self shape)
  325.                     (apply disclose-scode-list shape proc args)))))))
  326.  
  327. ;;; The special forms.
  328.  
  329. (define-local-syntax (define-compilator pat args . body)
  330.   (destructure (((name . foo) pat))
  331.     (let ((spect ((*value t-implementation-env 'arglist->argspectrum)
  332.                   foo)))
  333.       `(set (table-entry compilator-table
  334.                          (obtain-syntax-table-entry 
  335.                                (env-syntax-table (the-environment))
  336.                                ',name
  337.                                ',spect))
  338.             (lambda (#f %%exp%% . ,args)
  339.               (destructure ((,foo (cdr %%exp%%)))
  340.                 . ,body))))))
  341.  
  342. (define compilator-table (make-table 'compilator-table))
  343.  
  344. (define-compilator (quote thing) (shape fn?)
  345.   (ignore shape fn?)
  346.   (compile-literal thing))
  347.  
  348. (define (compile-literal obj)
  349.   (cond ((or (fixnum? obj)
  350.              (extend? obj))
  351.          (scode (lambda (lenv genv) (ignore lenv genv) obj)
  352.                 ((disclose-scode self shape)
  353.                  (ignore shape)
  354.                  `',obj)))
  355.         (else                              ; Hack - see RUN
  356.          obj)))
  357.  
  358. (define-compilator (call proc . rest) (shape fn?)
  359.   (compile-call (cons proc rest) fn?))
  360.   
  361. (define compiled-undefined-if-value
  362.   (compile-literal undefined-if-value))
  363.  
  364. (define-compilator (if test con . alts) (shape fn?)
  365.   (let ((test (compile test shape nil))
  366.         (con  (compile con shape fn?))  ; ??
  367.         (alt  (cond ((null? alts) compiled-undefined-if-value)
  368.                     ((null? (cdr alts))
  369.                      (compile (car alts) shape fn?))    ; ??
  370.                     (else
  371.                      (compile-error shape
  372.                                     "illegal IF syntax~%  ~S"
  373.                                     `(if ,test ,con ,@alts))))))
  374.     (scode (lambda (lenv genv)
  375.              (if (run test lenv genv) (run con lenv genv) (run alt lenv genv)))
  376.            ((disclose-scode self shape)
  377.             (cond ((eq? alt compiled-undefined-if-value)
  378.                    `(if ,@(disclose-scode-list shape test con)))
  379.                   (else
  380.                    `(if ,@(disclose-scode-list shape test con alt)))))
  381.            ((get-shape self) shape))))
  382.  
  383. (define-compilator (block . body) (shape fn?)
  384.   (compile-block body shape fn?))
  385.  
  386. (define (compile-block exp-list shape fn?)
  387.   (cond ((null-list? exp-list) (compile-literal nil))
  388.         ((null-list? (cdr exp-list)) (compile (car exp-list) shape fn?))
  389.         (else
  390.          (let ((code (map (lambda (exp) (compile exp shape nil))
  391.                           exp-list)))
  392.            (scode (lambda (lenv genv)
  393.                     (do ((c code (cdr c)))
  394.                         ((null? (cdr c)) (run (car c) lenv genv))
  395.                       (run (car c) lenv genv)))
  396.                   ((get-shape self) shape)
  397.                   ((disclose-scode self shape)
  398.                    `(block ,@(map (lambda (c)
  399.                                     (disclose-scode c shape))
  400.                                   code))))))))
  401.  
  402. ;;; LAMBDA.
  403.  
  404. (define-compilator (lambda vars . body) (shape fn?)
  405.   (compile-lambda nil vars body shape fn?))
  406.  
  407. (define-compilator (named-lambda name vars . body) (shape fn?)
  408.   (compile-lambda name vars body shape fn?))
  409.                           
  410. ;++ (define (duplicate-identifiers? arg-list)
  411. ;++   (iterate loop ((l arg-list))
  412. ;++     (cond ((memq? (car l) (cdr l))
  413. ;++            (error "LAMBDA with duplicate identifier in argument list - ~s~%"
  414. ;++                   (cons name arg-list)))
  415. ;++           (else (loop (cdr l))))))
  416.  
  417. ;++ changed for T3 objects and no more TC bug; removed statistics
  418. ;++ test for duplicate identifiers - see above
  419.  
  420. (define (compile-lambda name vars body-exps outer-shape fn?)
  421.   (let ((cenv (let ((others (shape-cenv outer-shape)))
  422.                 (cond ((null? vars) others) ; ****
  423.                       (else (add-contour vars others)))))
  424.         (spect (arglist->argspectrum vars)) ; unnecessary cons
  425.         (body nil))
  426.     (labels ((shape (object (lambda (lenv genv)
  427.                (object (lambda args           ; return a lexical closure
  428.                    (let ((nargs (compatible-with-argspectrum? args spect)))
  429.                      (cond ((not nargs)
  430.                             (handle-wrong-number-args (or name (disclose shape))
  431.                                                       spect
  432.                                                       args))
  433.                            ((and (fx= (car spect) 0) (not (cdr spect)))
  434.                             (run body lenv genv))
  435.                            (else
  436.                             (run body (add-contour args lenv) genv)))))
  437.                  ((get-environment self) (make-local-env outer-shape lenv))
  438.                  ((get-loaded-file self) (get-loaded-file outer-shape))
  439.                  ((identification self) name)
  440.                  ((argspectrum self) spect)
  441.                  ((disclose self) (disclose shape))))
  442.            ((scode? self) t)
  443.            ((shape-cenv self) cenv)
  444.            ((get-shape self) outer-shape)       ; ???!?
  445.            ((identification self) name)
  446.            ((disclose self)
  447.             `(lambda ,(cond ((and (fx= (car spect) 0) (not (cdr spect)))   '())
  448.                             (else (cenv-first cenv)))
  449.                . ,body-exps))
  450.            ((get-proc-name self)     ;For backtrace!
  451.             (or name (get-proc-name outer-shape)))
  452.            ((get-loaded-file self) (get-loaded-file outer-shape))
  453.            ((disclose-scode self shape) (ignore shape) (disclose self))
  454.            ((print-type-string self) "Open-procedure"))))
  455.     (set *scode-count* (fx+ *scode-count* 1))
  456.     (set body (compile-block body-exps shape nil))
  457.     shape)))
  458.  
  459. (define-operation (shape-cenv shape)
  460.   shape)
  461.  
  462. (define (handle-wrong-number-args name spectrum args)
  463.   (let ((n     (car spectrum))
  464.         (nary? (cdr spectrum)))
  465.     (error (list "wrong number of arguments to procedure -~%"
  466.                  "**~10t~s~%**~10t~s takes~a ~a argument~p.~%")
  467.            (cons name args)
  468.            name
  469.            (if nary? " at least" "")
  470.            n
  471.            n)))
  472.  
  473. (define-compilator (object . stuff) (shape fn?)
  474.   (compile (expand-object-form stuff) shape fn?))
  475.  
  476. ;;; -------------------- Other randomness.
  477.  
  478. (define-compilator (the-environment) (shape fn?)
  479.   (ignore fn?)
  480.   (scode (lambda (lenv genv)
  481.            (ignore genv)
  482.            (make-local-env shape lenv))
  483.          ((disclose-scode self shape)
  484.           (ignore shape)
  485.           '(the-environment))))
  486.  
  487. (define-compilator (bound? var) (shape fn?)
  488.   (ignore fn?)
  489.   (cond ((lambda-bound? shape var)
  490.          (compile-literal t))
  491.         (else
  492.          (scode (lambda (lenv genv)
  493.                   (ignore lenv)
  494.                   (*bound? (genv-env genv) var))))))
  495.  
  496. (define-compilator (lset-variable-value var val) (shape fn?)
  497.   (ignore fn?)
  498.   (compile-lbind var val shape nil))
  499.  
  500. (lset *current-definition* nil)
  501.  
  502. (define (current-definition) *current-definition*)
  503.  
  504. (define-compilator (define-variable-value var val) (shape fn?)
  505.   (ignore fn?)
  506.   (bind ((*current-definition* var))
  507.     (compile-lbind var val shape t)))
  508.  
  509. (define (compile-lbind var val shape define?)
  510.   (cond ((lambda-bound? shape var)
  511.          (warning "~S or ~S on a ~S-bound variable~%  ~G~%"
  512.                   'define 'lset 'lambda
  513.                   `(,(if define? 'define 'lset) ,var ,val))
  514.          (compile `(,(t-syntax 'set-variable-value) ,var ,val)
  515.                   shape nil))
  516.         (else
  517.          (let ((valx (compile val shape nil)))
  518.            (scode (lambda (lenv genv)
  519.                     ((if define? *define *lset)
  520.                      (genv-env genv) var (run valx lenv genv)))
  521.                   ((get-shape self) shape)
  522.                   ((disclose-scode self shape)
  523.                    `(,(if define? 'define 'lset)
  524.                      ,var ,(disclose-scode valx shape))))))))
  525.  
  526. ;;; Local syntax: DEFINE-LOCAL-SYNTAX, LET-SYNTAX
  527.  
  528. (define-compilator (define-local-syntax . spec) (shape fn?)
  529.   (ignore fn?)
  530.   (compile-literal (set-local-syntax *syntax-table* spec)))
  531.  
  532. (define-compilator (let-syntax specs . body) (shape fn?)
  533.   (let ((syntax (make-syntax-table *syntax-table* nil)))
  534.     (walk (lambda (spec)
  535.             (set-local-syntax syntax spec))
  536.           specs)
  537.     (bind ((*syntax-table* syntax))
  538.       (compile-block body shape fn?))))
  539.  
  540. (define (set-local-syntax syntax spec)        ;auxiliary for above
  541.   (let ((pat (car spec))
  542.         (body (cdr spec)))
  543.     (receive (sym exp)
  544.              (cond ((pair? pat)
  545.                     (return (car pat)
  546.                             `(,(t-syntax 'macro-expander) ,pat . ,body)))
  547.                    (else
  548.                     (return pat (car body))))
  549.       (set (syntax-table-entry syntax sym)
  550.            (eval exp (env-for-syntax-definition syntax)))
  551.       sym)))
  552.  
  553. ;++ flush (define-compilator (locale var . body) (shape fn?)
  554. ;  (ignore fn?)
  555. ;  (let ((code (compile-top (blockify body)
  556. ;                           *syntax-table*
  557. ;                           (get-loaded-file shape))))
  558. ;    (scode (lambda (lenv genv)
  559. ;             (let ((new-env (make-locale (make-local-env shape lenv)
  560. ;                                         var)))
  561. ;               (if var
  562. ;                   (bind (((print-env-warnings?) nil))
  563. ;                     (*define new-env var new-env)))
  564. ;               (run-compiled-code code new-env)))
  565. ;           ((disclose-scode self shape)
  566. ;            `(locale ,var ,@body)))))
  567.  
  568. ;;; Implement LABELS as a source rewrite.
  569.  
  570. (define-compilator (labels specs . body) (shape fn?)
  571.   (compile
  572.    (iterate loop ((s specs)
  573.                   (vars '())
  574.                   (inits '()))
  575.     (cond ((null-list? s)
  576.            `((,(t-syntax 'lambda) ,vars
  577.                ,@(reverse! inits)
  578.                . ,body)
  579.              ,@(map (lambda (var) (ignore var) 'unbound-label)
  580.                     vars)))
  581.           (else
  582.            (let ((spec (car s)))
  583.              (cond ((atom? spec)
  584.                     (syntax-error "bad ~S spec~%  (~S (... ~S ...) ...)"
  585.                                   'labels 'labels spec))
  586.                    ((atom? (car spec))
  587.                     (loop (cdr s)
  588.                           (cons (car spec) vars)
  589.                           (cons `(,(t-syntax 'set-variable-value) ,@spec)
  590.                                 inits)))
  591.                    (else
  592.                     (loop (cdr s)
  593.                           (cons (caar spec) vars)
  594.                           (cons `(,(t-syntax 'set-variable-value)
  595.                                   ,(caar spec)
  596.                                   (,(t-syntax 'lambda) ,(cdar spec)
  597.                                                        ,@(cdr spec)))
  598.                                 inits))))))))
  599.   shape fn?))
  600.  
  601. (define-compilator (declare . stuff) (shape fn?)
  602.   (ignore fn?)
  603.   (compile-literal 'declare))
  604.  
  605. (define-compilator (primop . stuff) (shape fn?)
  606.   (ignore fn?)
  607.   (error "primops don't interpret yet -~%~10t~s" '(primop . ,stuff)))
  608.  
  609. (define-compilator (define-foreign . stuff) (shape fn?)
  610.   (ignore fn?)
  611.   (error "foreign definitions don't interpret yet -~%~10t~S" 
  612.          '(define-foreign . ,stuff)))
  613.  
  614. ;;; Generally useful utility:
  615.  
  616. (define (compile-error shape . rest)
  617.   (compile (apply syntax-error rest) shape nil))
  618.  
  619. ;;; -------------------- Variable and environment stuff.
  620.  
  621. ;;; Three primitive operations on variable bindings: fetch, store, locative.
  622.  
  623. (define-compilator (variable-value var) (shape fn?)
  624.   (compile-var var shape fn?))
  625.  
  626. (define (compile-var var shape fn?)
  627.   (and fn?
  628.        (syntax-table-entry *syntax-table* var)
  629.        (warning "call to variable ~S is not being treated as a special form~%"
  630.                 var))
  631.   (cond ((shape-lookup shape var)
  632.          => (lambda (spec) (compile-lexvar spec)))
  633.         (else
  634.          (compile-static shape var))))
  635.  
  636. (define-compilator (set-variable-value var val) (shape fn?)
  637.   (ignore fn?)
  638.   (let ((valx (compile val shape nil)))
  639.     (cond ((shape-lookup shape var)
  640.            => (lambda (spec) (compile-set-lexvar spec valx)))
  641.           (else
  642.            (compile-assign-static valx shape var)))))
  643.  
  644. (define-compilator (var-locative var) (shape fn?)
  645.   (ignore fn?)
  646.   (cond ((shape-lookup shape var)
  647.          => (lambda (spec)
  648.               (scode (lambda (lenv genv)
  649.                        (ignore genv)
  650.                        (lexvar-locative var spec lenv))
  651.                      ((get-shape self) shape))))
  652.         (else
  653.          (compile-static-locative var shape))))
  654.  
  655. ;;; Fetch, store and locative operations for static variables:
  656.  
  657. ;;; Returns a ZZ pair (var . index)
  658.  
  659. (define (get-static-zz var)
  660.   (or (table-entry *free-vars* var)
  661.       (set (table-entry *free-vars* var)
  662.            (cons var (swap *free-var-count* (fx+ *free-var-count* 1))))))
  663.  
  664. (define-integrable (get-locative genv zz)
  665.   (or (vref genv (cdr zz))
  666.       (really-get-locative genv zz)))
  667.  
  668. (define (really-get-locative genv zz)
  669.   (cond ((env-lookup (genv-env genv) (car zz) nil nil)
  670.          => (lambda (loc)
  671.               (vset genv (cdr zz) loc)
  672.               loc))
  673.         (else
  674.          (object nil
  675.            ((contents self)
  676.             (cond ((vref genv (cdr zz)) => contents)
  677.                   (else
  678.                    (error "variable ~S is unbound" (car zz)))))
  679.            ((set-contents self val)
  680.             (cond ((vref genv (cdr zz))
  681.                    => (lambda (loc) (set-contents loc val)))
  682.                   (else
  683.                    (vset genv
  684.                          (cdr zz)
  685.                          (reluctantly-bind (genv-env genv) (car zz)))
  686.                    (set-contents self val))))
  687.            ((locative? self) t)
  688.            ((print-type-string self) "Locative")))))
  689.  
  690. (define (compile-static shape var)
  691.   (let ((zz (get-static-zz var)))
  692.     (scode (lambda (lenv genv)
  693.              (ignore lenv)
  694.              (let ((loc (get-locative genv zz)))
  695.                (cond ((vcell? loc)
  696.                       (let ((z (vcell-contents loc)))
  697.                         (cond ((nonvalue? z)
  698.                                (no-op (error "bound variable ~S has no value"
  699.                                              (car zz))))
  700.                               (else z))))
  701.                      (else
  702.                       (contents loc)))))
  703.            ((get-shape self) shape)
  704.            ((disclose-scode self shape)
  705.             (ignore shape)
  706.             (let ((var (car zz)))
  707.               (cond ((and (symbol? var)
  708.                           (not (syntax-table-entry standard-syntax-table
  709.                                                    var)))
  710.                      var)
  711.                     (else `(variable-value ,var))))))))
  712.  
  713. (define (compile-assign-static valx shape var)
  714.   (let ((zz (get-static-zz var)))
  715.     (scode (lambda (lenv genv)
  716.              (let ((val (run valx lenv genv))
  717.                    (loc (get-locative genv zz)))
  718.                (set-contents loc val)))                  
  719.            ((get-shape self) shape)
  720.            ((disclose-scode self shape)
  721.             `(set ,(car zz) ,(disclose-scode valx shape))))))
  722.  
  723. (define (compile-static-locative var shape)
  724.   (let ((zz (get-static-zz var)))
  725.     (scode (lambda (lenv genv)
  726.              (ignore lenv)
  727.              (get-locative genv zz))
  728.            ((get-shape self) shape))))
  729.  
  730. ;;; Local environment stuff
  731.  
  732. (define (heuristically-lenv? obj)
  733.   (iterate loop ((l obj) (i 0))
  734.     (cond ((lenv-end? l)
  735.            (if (environment? l) obj nil))
  736.           ((not (proper-list? (lenv-first l))) nil)
  737.           ((fx> i 1000) nil)    ; Circularity hack
  738.           (else
  739.            (loop (lenv-rest l) (fx+ i 1))))))
  740.  
  741. (define (lenv-end lenv)
  742.   (cond ((atom? lenv) lenv)
  743.         (else (lenv-end (lenv-rest lenv)))))
  744.  
  745. ;;; Shape lookup stuff.
  746.  
  747. ;;; (SHAPE-LOOKUP shape exp) -> lvspec or false
  748. ;;;     Returns either a local variable spec (lvspec), which is actually
  749. ;;;     a fixnum in two bit fields, or false if the variable isn't
  750. ;;;     locally bound.
  751.  
  752. (define (lambda-bound? shape var)
  753.   (shape-lookup shape var))
  754.  
  755. ;;; Look for local variable in SHAPE; return an LVSPEC if there is
  756. ;;; one.  Returns false if no local variable exists.
  757.  
  758. (define (shape-lookup shape var)
  759.   (iterate loop1 ((v (shape-cenv shape))
  760.                   (m 0))
  761.     (cond ((cenv-end? v) nil)
  762.           (else
  763.            (iterate loop2 ((w (cenv-first v))
  764.                            (n 1))               ; ?
  765.              (cond ((atom? w)
  766.                     (cond ((eq? var w) (lvspec m (fx- 0 n)))
  767.                           (else (loop1 (cenv-rest v) (fx+ m 1)))))
  768.                    ((eq? var (car w))
  769.                     (lvspec m n))       ; success
  770.                    (else
  771.                     (loop2 (cdr w) (fx+ n 1)))))))))
  772.  
  773. (define (make-local-env shape lenv)          
  774.   (cond ((lenv-end? lenv) lenv)
  775.         (else
  776.          (object (lambda (var local? create?)
  777.                    (cond ((or local? create?)
  778.                           (error '("illegal to create new bindings"
  779.                                    " in this environment~%  ~S")
  780.                                  `(env-lookup ... ,var ,local? ,create?)))
  781.                          ((shape-lookup shape var)
  782.                           => (lambda (spec)
  783.                                (lexvar-locative var spec lenv)))
  784.                          (else
  785.                           (env-lookup (lenv-end lenv) var local? create?))))
  786.            ((env-superior self) (lenv-end lenv))
  787.            ((walk-local-env self proc)
  788.             (really-walk-local-env (shape-cenv shape) lenv proc))
  789.            ((crawl-exhibit-env self)
  790.             (format (terminal-output) "Local variable environment:~%")
  791.             (walk-local-env self
  792.                      (lambda (var val)
  793.                        (let ((to (terminal-output)))
  794.                          (format to "  ~8S = " var)
  795.                          (print-one-line val to)
  796.                          (fresh-line to))))
  797.             (format (terminal-output) "Outer environment: ~S~%"
  798.                     (lenv-end lenv)))
  799.            ((get-environment self) self)
  800.            ((get-loaded-file self)
  801.             (get-loaded-file (env-superior self)))
  802.            ((environment? self) t)
  803.            ((print-type-string self) "Environment")))))
  804.  
  805.  
  806. (define-operation (walk-local-env env proc))
  807.  
  808. (define (really-walk-local-env cenv lenv proc)
  809.   (iterate loop1 ((v cenv)
  810.                   (e lenv))
  811.     (cond ((cenv-end? v) nil)
  812.           (else
  813.            (iterate loop2 ((w (cenv-first v))
  814.                            (f (lenv-first e)))
  815.              (cond ((atom? w)
  816.                     (cond ((not (null? w))
  817.                            (proc w f)))
  818.                     (loop1 (cenv-rest v) (lenv-rest e)))
  819.                    (else
  820.                     (proc (car w) (car f))
  821.                     (loop2 (cdr w) (cdr f)))))))))
  822.  
  823. ;;; Given a local variable spec, and the shape to which it's relative,
  824. ;;; return the name of the variable.  This depends on the fact that
  825. ;;; shapes and local environments have the same representation!
  826.  
  827. (define (invert-lvspec shape lvspec)
  828.   (run (compile-lexvar lvspec) (shape-cenv shape) 'lose))
  829.  
  830. ;;; Fetch, store, locative for local variable.
  831.  
  832. (lset *scode-lexvar-count* 0)
  833.  
  834. (define (compile-lexvar spec)
  835.   (set *scode-lexvar-count* (fx+ *scode-lexvar-count* 1))
  836.   spec)
  837.  
  838. (define (compile-set-lexvar spec valx)
  839.   (scode (lambda (lenv genv)
  840.            (store-into-lenv spec lenv (run valx lenv genv)))
  841.          ((disclose-scode self shape)
  842.           `(set ,(invert-lvspec shape spec)
  843.                 ,(disclose-scode valx shape)))))
  844.  
  845. (define (lexvar-locative var spec lenv)
  846.   (object nil
  847.           ((contents self)
  848.            (fetch-from-lenv spec lenv))
  849.           ((set-contents self value)
  850.            (store-into-lenv spec lenv value))
  851.           ((locative? self) t)
  852.           ((identification self) var)
  853.           ((print-type-string self) "Locative")))
  854.  
  855. ;;; Get the value of a local variable.
  856.  
  857. (define (fetch-from-lenv spec lenv)
  858.   (cond ((fx> (lvspec-over spec) 0)     ; conditional moved out of middle
  859.          (let ((back (lvspec-back spec))
  860.                (over (lvspec-over spec)))
  861.             (do ((e1 lenv (lenv-rest e1))
  862.                  (i1 0 (fx+ i1 1)))
  863.                 ((fx= i1 back)
  864.                  (do ((e2 (lenv-first e1) (cdr e2))
  865.                       (i2 1 (fx+ i2 1)))
  866.                      ((fx= i2 over) (car e2)))))))
  867.         (else
  868.          (let ((back (lvspec-back spec))
  869.                (over (lvspec-over spec)))
  870.            (do ((e1 lenv (lenv-rest e1))
  871.                 (i1 0 (fx+ i1 1)))
  872.                ((fx= i1 back)
  873.                 (do ((e2 (lenv-first e1) (cdr e2))
  874.                      (i2 -1 (fx- i2 1)))
  875.                     ((fx= i2 over) e2))))))))
  876.  
  877. ;;; Set the value of a local variable.
  878.  
  879. (define (store-into-lenv spec lenv val)
  880.   (let ((back (lvspec-back spec))
  881.         (over (lvspec-over spec)))
  882.     (do ((e1 lenv (lenv-rest e1))
  883.          (i1 0 (fx+ i1 1)))
  884.         ((fx= i1 back)
  885.          (cond ((fx> over 0)
  886.                 (do ((e2 (lenv-first e1) (cdr e2))
  887.                      (i2 1 (fx+ i2 1)))
  888.                     ((fx= i2 over) (set (car e2) val))))
  889.                (else
  890.                 ;; LENV-FIRST here assumed to be same as CDR!
  891.                 (do ((e2 e1 (cdr e2))
  892.                      (i2 -1 (fx- i2 1)))
  893.                     ((fx= i2 over) (set (cdr e2) val)))))))))
  894.